跳到主要内容

08. Configuration

 BaseModel.model_config 用于配置 BaseModel 的行为

from pydantic import BaseModel, ConfigDict, ValidationError

class Model(BaseModel):
model_config = ConfigDict(str_max_length=10)

v: str

try:
m = Model(v='x' * 20)
except ValidationError as e:
print(e)
"""
1 validation error for Model
v
String should have at most 10 characters [type=string_too_long, input_value='xxxxxxxxxxxxxxxxxxxx', input_type=str]
"""

当然,直接在类参数中传入配置项也是可行的

from pydantic import BaseModel, ValidationError


class Model(BaseModel, extra='forbid'):
a: str


try:
Model(a='spam', b='oh no')
except ValidationError as e:
print(e)
"""
1 validation error for Model
b
Extra inputs are not permitted [type=extra_forbidden, input_value='oh no', input_type=str]
"""

使用 dataclass 的时候,也能在装饰器中传入设置项

from datetime import datetime

from pydantic import ConfigDict, ValidationError
from pydantic.dataclasses import dataclass

config = ConfigDict(str_max_length=10, validate_assignment=True)


@dataclass(config=config)
class User:
id: int
name: str = 'John Doe'
signup_ts: datetime = None


user = User(id='42', signup_ts='2032-06-21T12:00')
try:
user.name = 'x' * 20
except ValidationError as e:
print(e)
"""
1 validation error for User
name
String should have at most 10 characters [type=string_too_long, input_value='xxxxxxxxxxxxxxxxxxxx', input_type=str]
"""

dataclassTypedDict 中使用设置项

使用 __pydantic_config__

from dataclasses import dataclass
from datetime import datetime

from pydantic import ConfigDict

@dataclass
class User:
__pydantic_config__ = ConfigDict(strict=True)

id: int
name: str = 'John Doe'
signup_ts: datetime = None

Alternatively, the with_config decorator can be used to comply with type checkers.

from typing_extensions import TypedDict

from pydantic import ConfigDict, with_config


@with_config(ConfigDict(str_to_lower=True))
class Model(TypedDict):
x: str

全局性配置

可以创建一个继承自 BaseModel 的基础 model 类,达成全局性配置的目的

from pydantic import BaseModel, ConfigDict


class Parent(BaseModel):
model_config = ConfigDict(extra='allow')

class Model(Parent):
x: str

m = Model(x='foo', y='bar')
print(m.model_dump())
#> {'x': 'foo', 'y': 'bar'}

If you add a model_config to the Model class, it will merge with the model_config from Parent:

from pydantic import BaseModel, ConfigDict

class Parent(BaseModel):
model_config = ConfigDict(extra='allow')

class Model(Parent):
model_config = ConfigDict(str_to_lower=True) # (1)!

x: str


m = Model(x='FOO', y='bar')
print(m.model_dump())
#> {'x': 'foo', 'y': 'bar'}
print(m.model_config)
#> {'extra': 'allow', 'str_to_lower': True}

配置项

Configuration - Pydantic

  • title
    • str,The title for the generated JSON schema, defaults to the model's name
  • str_to_lower、str_to_upper
    • bool,是否将所有字符串大写 / 小写
  • str_strip_whitespace
    • bool,是否移除前后空白字符
  • str_min_length、str_max_length
    • int,字符串最短 / 最长长度
  • extra
    • ExtraValues,在初始化 model 时,针对额外传入的参数的行为
    • allow - Allow any extra attributes.
    • forbid - Forbid any extra attributes. 遇到额外字段会报错
    • ignore - Ignore any extra attributes. Default value.
  • frozen
    • bool,model 是否不变(faux-immutable)
    •  i.e. whether __setattr__ is allowed, and also generates a __hash__() method for the model. This makes instances of the model potentially hashable if all the attributes are hashable.
  • populate_by_name
    • bool,Whether an aliased field may be populated by its name as given by the model attribute, as well as the alias. Defaults to False.
    • bool,针对别名字段,能否使用原名来填充 model
from pydantic import BaseModel, ConfigDict, Field

class User(BaseModel):
model_config = ConfigDict(populate_by_name=True)

name: str = Field(alias='full_name')
age: int


user = User(full_name='John Doe', age=20) # The model is populated by the alias 'full_name'.
print(user)
#> name='John Doe' age=20
user = User(name='John Doe', age=20) # 如果 populate_by_name=False,则会报错
print(user)
#> name='John Doe' age=20
  • use_enum_values
    • bool,是否使用枚举的值本身来填充 models,而不是枚举值
    • This may be useful if you want to serialize model.model_dump() later. Defaults to False.
from enum import Enum
from typing import Optional

from pydantic import BaseModel, ConfigDict, Field

class SomeEnum(Enum):
FOO = 'foo'
BAR = 'bar'
BAZ = 'baz'

class SomeModel(BaseModel):
model_config = ConfigDict(use_enum_values=True)

some_enum: SomeEnum
another_enum: Optional[SomeEnum] = Field(default=SomeEnum.FOO, validate_default=True)

model1 = SomeModel(some_enum=SomeEnum.BAR)
print(model1.model_dump())
# {'some_enum': 'bar', 'another_enum': 'foo'}

model2 = SomeModel(some_enum=SomeEnum.BAR, another_enum=SomeEnum.BAZ)
print(model2.model_dump())
#> {'some_enum': 'bar', 'another_enum': 'baz'}

# 如果设置为False的话,则会输出
#> {'some_enum': <SomeEnum.BAR: 'bar'>, 'another_enum': <SomeEnum.FOO: 'foo'>}
#> {'some_enum': <SomeEnum.BAR: 'bar'>, 'another_enum': <SomeEnum.BAZ: 'baz'>}
  • validate_assignment
    • bool,当 model 值改变时,是否重新 validate 一遍
    • Pydantic 默认的行为是:只在创建时验证
from pydantic import BaseModel, ValidationError

class User(BaseModel, validate_assignment=True):
name: str

user = User(name='John Doe')
print(user)
#> name='John Doe'
try:
user.name = 123
except ValidationError as e:
print(e)
'''
1 validation error for User
name
Input should be a valid string [type=string_type, input_value=123, input_type=int]
'''
  • arbitrary_types_allowed
    • bool,字段类型是否允许使用任意类型
from pydantic import BaseModel, ConfigDict

# This is not a pydantic model, it's an arbitrary class
class Pet:
    def __init__(self, name: str):
        self.name = name

class Model(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)

    pet: Pet
    owner: str

TBD